package sv_schedule

import (
	"time"
	"venus/core"
	"venus/util/zlog"
	"venus/util/ztime"
)

type SchType int //服务器触发器类型

const (
	PerSecond        SchType = iota //每秒
	PerSecond10                     //每10秒
	PerMinute                       //每分
	PerHour                         //每小时
	OClock                          //整点
	OClock0                         //整0点
	OClock5                         //整5点
	OClock6                         //整6点
	BeginSunday                     //每周日0点
	BeginMonday                     //每周一0点
	BeginMonth                      //每月初
	ServeTrigTypeMax                //结束
)

// SvSchedule 定时事件服务
type SvSchedule struct {
	BindMap map[SchType][]func() //触发列表
	//EvtChan chan *Evt //主事件队列

	tSchedule time.Time //上次触发时间

	tPerSecond   time.Time
	tPerSecond10 time.Time
	tPerMinute   time.Time
	tPerHour     time.Time
	tOClock      time.Time
	tOClock0     time.Time
	tOClock5     time.Time
	tOClock6     time.Time
	tBeginSunday time.Time
	tBeginMonday time.Time
	tBeginMonth  time.Time
}

var _Sv *SvSchedule

// NewSv 定时服务
func NewSv(fnRegisters ...func()) *SvSchedule {
	_Sv = new(SvSchedule)
	_Sv.BindMap = make(map[SchType][]func())
	for _, fn := range fnRegisters {
		fn()
	}
	return _Sv
}

func (sv *SvSchedule) Init() {
	zlog.Info(sv.Name() + " Init")

	core.BindMsgExec(core.MsgTypeSchedule, sv.Exec)
}

func (sv *SvSchedule) Run() {
	zlog.Info(sv.Name() + " Run")

	for {
		sv.loop()

		time.Sleep(time.Millisecond * 100)
	}
}

func (sv *SvSchedule) Destroy() {
	zlog.Info(sv.Name() + " Destroy")
}

func (sv *SvSchedule) Name() string {
	return "SvSchedule"
}

func (sv *SvSchedule) loop() {

	dt := time.Now()
	sv.tSchedule = dt
	//zlog.Info(service.Name() + " loop", service.tSchedule)

	if dt.After(sv.tPerSecond) {
		for _, s := range sv.BindMap[PerSecond] {
			AddMsg(s)
		}
		sv.tPerSecond = dt.Add(time.Second)
	}
	if dt.After(sv.tPerSecond10) {
		for _, s := range sv.BindMap[PerSecond10] {
			AddMsg(s)
		}
		sv.tPerSecond10 = dt.Add(time.Second * 10)
	}
	if dt.After(sv.tPerMinute) {
		for _, s := range sv.BindMap[PerMinute] {
			AddMsg(s)
		}
		sv.tPerMinute = dt.Add(time.Minute)
	}
	if dt.After(sv.tPerHour) {
		for _, s := range sv.BindMap[PerHour] {
			AddMsg(s)
		}
		sv.tPerHour = dt.Add(time.Hour)
	}
	if !ztime.SameHour(dt, sv.tOClock) {
		for _, s := range sv.BindMap[OClock] {
			AddMsg(s)
		}
		sv.tOClock = dt
	}
	if !ztime.SameHour(dt, sv.tOClock0) && dt.Hour() == 0 {
		for _, s := range sv.BindMap[OClock0] {
			AddMsg(s)
		}
		sv.tOClock0 = dt
	}
	if !ztime.SameHour(dt, sv.tOClock5) && dt.Hour() == 5 {
		for _, s := range sv.BindMap[OClock5] {
			AddMsg(s)
		}
		sv.tOClock5 = dt
	}
	if !ztime.SameHour(dt, sv.tOClock6) && dt.Hour() == 6 {
		for _, s := range sv.BindMap[OClock6] {
			AddMsg(s)
		}
		sv.tOClock6 = dt
	}
}

func (sv *SvSchedule) Bind(t SchType, fn func()) {
	sv.BindMap[t] = append(sv.BindMap[t], fn)
}

func (sv *SvSchedule) Exec(e *core.Msg) {
	e.Data.(func())()
}

func AddMsg(fn func()) {
	msg := &core.Msg{
		Type: core.MsgTypeSchedule,
		Data: fn,
	}
	core.AddMsg(msg)
}
